/*
 * This file is part of the openHiTLS project.
 *
 * openHiTLS is licensed under the Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include "hitls_build.h"
#if defined(HITLS_CRYPTO_ECC) && defined(HITLS_CRYPTO_SM2)

#include <stdint.h>
#include "securec.h"
#include "crypt_ecc.h"
#include "ecc_local.h"
#include "crypt_utils.h"
#include "crypt_errno.h"
#include "bsl_sal.h"
#include "bsl_err_internal.h"
#include "asm_ecp_sm2.h"

static const uint64_t g_sm2Precompute[8 * 256] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    /* Base point G */
    0x715a4589334c74c7, 0x8fe30bbff2660be1, 0x5f9904466a39c994, 0x32c4ae2c1f198119, 0x02df32e52139f0a0, 0xd0a9877cc62a4740, 0x59bdcee36b692153, 0xbc3736a2f4f6779c,
    /* 2 * G */
    0x495c2e1da3f2bd52, 0x9c0dfa08c08a7331, 0x0d58ef57fa73ba4d, 0x56cefd60d7c87c00, 0x6f780d3a970a23c3, 0x6de84c182f6c8e71, 0x68535ce0f8eaf1bd, 0x31b7e7e6cc8189f6,
    /* 3 * G */
    0xe26918f1d0509ebf, 0xa13f6bd945302244, 0xbe2daa8cdb41e24c, 0xa97f7cd4b3c993b4, 0xaaacdd037458f6e6, 0x7c400ee5cd045292, 0xccc5cec08a72150f, 0x530b5dd88c688ef5,
    0xb21646cd34a0ced5, 0x009a084ad5cc937d, 0x2a81052ff641ed69, 0xc239507105c68324, 0x7a253666cb66e009, 0x6bee2e96ab8c71fb, 0x35f1294ac0db1968, 0xb1bf7ec4080f3c87,
    0xa575da57cc372a9e, 0x344a417b7fce19db, 0x040e008fdd5eb77a, 0xc749061668652e26, 0xa6976eff5fbe6480, 0x5006206eb579ff7d, 0x4504c622b51cf38f, 0xf2df5db2d144e945,
    0x2c8b1a1a3c4b0d30, 0x05ff8856a6601689, 0xbb17c93e71f22a31, 0x0927afb57d93483b, 0xd572103000088f63, 0x81adf1f0855a064d, 0xac1c0ef6ebf26645, 0x150c6b1ab4d1fc7e,
    0xcd27e384d9fcaf15, 0xa80198337744ee78, 0xfdbe86a75c139906, 0xddf092555409c19d, 0x223b949657e52bc1, 0x037937707d6a49a2, 0x5cd6b6e9c12d2922, 0x847d18ffb38e8706,
    0x675d822ded0bb916, 0xd4ea35d60c1c29bb, 0x3db4333d4e860e64, 0xb9c3faeb4b161071, 0x3c286da2cfd31a3e, 0x0366a8a03024b3e0, 0x2491d2de9accf2be, 0xc519b309ecf7269c,
    0x173472a58cca247e, 0xfe8d59cb43619e4f, 0x0b4a2444a46a74c5, 0xa27233f3a5959508, 0x85227940922c02e9, 0xc3a8433140d1ebca, 0x768f7689b210f45f, 0x379e72f63722c924,
    0x84a04814db522756, 0xb2d0d065cd219e32, 0x21666061f65c3e32, 0xd3f94862519621c1, 0x47d46fb2bab82a14, 0xf6b743f64d1482d1, 0x2ebd57d146dca428, 0x4b9030cf676f6a74,
    0x668c74d78ce20ace, 0x125dcdd589c2ff82, 0x7c1aab770f67f543, 0x04b3cb10c9c6d8e2, 0x739a8fd805174a4b, 0x0c94816e63c4bc72, 0x4918e5c02e2b0b93, 0x63516355287e39fe,
    0x9c9f042d0279270a, 0x5f7b516c5bdaddad, 0xd89058ca059be46e, 0xbfc2df6bb17f971a, 0xb5fbf87b64af3c26, 0x73c9fc6fd150aaaa, 0xcef696b67939bd7b, 0xb145513f59636106,
    0x2b834f1d509b9cd0, 0x7bea65c6421e189e, 0xfa804513275f58aa, 0x952072d6ff9c65bd, 0x03891e105e009b00, 0x58d1434ae934ba75, 0x1a473f8d9748f238, 0xe6bb9804458bb70f,
    0x0a44248a36bb0a07, 0xef22ea28be9d44de, 0x4aaf81826982d748, 0x83b4a4de96a4d70f, 0x2e663cd4373a2f24, 0x3e707c8a43852949, 0xeeb6d6c6d7e74f8e, 0xe481c0d9ee8a98d4,
    0x461b1bbcb80f829c, 0x3b424f35f0ecce4c, 0x3291676c38d39324, 0xf73b839f13912c1a, 0x4c3533771db0955e, 0xdc2e788fb170aa14, 0x5ee9fab985c12455, 0x32ec7722695dc7cf,
    0x55645bbc8704fb68, 0xea133cd248a93e25, 0xbbce44ef5db3e419, 0x35648233f554ae51, 0x4411a9a30eca2046, 0x154b1870a6a65166, 0x6117bca9ce885dd6, 0x04d7ac60f6d975ef,
    0x36969f8b77125e6a, 0xbf5113ab85b5ed44, 0x1c993f01115c57f7, 0xdd18aa4aec26eac4, 0xe0180d54d4ae2221, 0x6cce6001d7c0b853, 0x3361493f76fac50f, 0x161e5851969da822,
    0x427e33ae8ed9c317, 0xa3448557a24554db, 0x221ea8657781ce71, 0x69fdf8a436fd8e5d, 0x71e35709341fdcab, 0xeb7b1ad657c155f5, 0x6b0a9658b33b347b, 0xbaa856d1cad68af3,
    0x1323f252e493952a, 0xf7c96c55940a4726, 0xe2e0586bb5dc9419, 0xa68b2ec49d1921d0, 0xfd4520a63f5cc585, 0xb95f2de69200269e, 0x933ef442fca7a734, 0x96f361a23b3deb99,
    0x0588fdd88abdee94, 0xabbb1ea1417f958d, 0x7575e3cb2fa9092d, 0x08314765e44847eb, 0x5eeb0e99c2eb61e9, 0x7de3a53937e8a75f, 0x6b443ab436095378, 0xdf922344fa592a98,
    0xe1de5f100950c8ab, 0x5b551c86a8976933, 0x137cbf4e8aa50535, 0x6407be639bc5b738, 0xf945321148e90344, 0x60fcfd988fff6dec, 0x12a9423fd80dea54, 0x141caee612e7ab07,
    0x0755a352dafa1e1d, 0x3e7307f46fa550d1, 0x1835a4d0f3e5e299, 0xe61120569974c0bc, 0x3b86cc142850b0f3, 0x02855e18d12379b4, 0xd08fc10e5056e4bc, 0xcfe30aa2c3877e52,
    0x4dbb2fcd069d45db, 0xbb570a9f430ea7f6, 0x15c07a8c04226fe3, 0xac8df677299e8288, 0x7bd8b7c847718ce5, 0x0e9b9643d766da33, 0x30c43be69b23cc14, 0xaef82cf361db1c71,
    0xd7240a35d1f4ffed, 0xec268911ccb79283, 0x314fa6c814c7bda8, 0xdf8a74f904d1715e, 0xbcb60a9e82017c30, 0xe1c80e7752bd6499, 0x7a7606ef148aa5fb, 0x0fed448a3f263918,
    0x0263b20d539e4139, 0x7e8581fbbcf5de01, 0xce1564c3df7d67ea, 0x178d1f6bd584afcc, 0x9b499a7da7820bf9, 0x7021aafc29ac8e86, 0x53da45cec1caada1, 0xf575f34e5f6c63c6,
    0x8e6a9e4fdf895290, 0x73783ef304251e74, 0xbcf26fe238a102c2, 0xa0a1a4fbeb476576, 0xe54f7f3a4896d9d3, 0xec73068587361b34, 0x0d09c3f281d4c41c, 0x8dfdd7cd150d2564,
    0xce37e84fc9541b4b, 0x02a85a7410754529, 0xd7a1f169475b4ddf, 0xec6f34ceacaa73a0, 0x73306a0ff0485872, 0xe607f33be20135ea, 0x6f251c63fbbd2927, 0x3c85cf62a744817e,
    0x6cb2f058c747d33f, 0x36f0dfe49113c16e, 0x94ed53ed581d191d, 0x91cb72dc55f84346, 0x3ea6aace93921f31, 0xf4c600e8b5dfe811, 0xf7efb07682931f88, 0x1957ad4cfffd491e,
    0x9dd4ef421635b9dc, 0xc9816be068be66db, 0x625773cae69bbe05, 0x28221c36398c4c3a, 0x2995225e66b162ba, 0x64c77a81858d4ca1, 0xab2012c41627cd81, 0x3b4d172d6963510b,
    0xfd23ea021da51c9d, 0x8b1ac02e98d543ce, 0xc315796922bf1343, 0x17a5f74d533ae724, 0x57d2e81dbb945dfe, 0x7befa4db8c8d3eff, 0xb9038823d9ad0d5f, 0x498470ec6752b2ec,
    0xac995c5066bdaaa5, 0x27d053c0f150fe10, 0xd6b48259b69e8530, 0x08daae840b2a43eb, 0x2458b9e3c73bf657, 0xf7dc310560bbe83a, 0xc1b8e58150da662d, 0x80cc0a980495af87,
    0xa32641e56024666c, 0x791734cd03e5565c, 0xa6d5c2b5817f2329, 0x25d3debd0950d180, 0xd39e100303fa10a2, 0x0458895120e208b4, 0xb938c406dd5cb0e1, 0x92d99a70679d61ef,
    0x6d69b1bd07837dc9, 0x451641e8455eedb6, 0x4624f85fe9b7cb83, 0xa1aa7f4a42808908, 0xc3c8bd75b5fe25de, 0x6e67fd81941c6a60, 0xeb15fccc63694830, 0x3d420dee447499cf,
    0x37a60fce33247b4c, 0x1afddac4a9667094, 0x72e11351388e9d3d, 0x87e13ab96307c971, 0x217ed12bbc413d35, 0xd7ac6191958240c7, 0xadb32c8ad1d8a615, 0x3ff4e73fac0283e5,
    0x549786448c4f3f4d, 0xbaf30f4638d2231b, 0x46dab2eba04afd78, 0x68126a90b051062b, 0x5a8ce092c6b7c016, 0xe7fec8984be51251, 0x35ecf208bdec5980, 0x7e72f70a2eaf1bf4,
    0xfa2f46cf90a47d2b, 0xe7579164cc5a233c, 0xcdd2cc00d6ce411e, 0x323159ac22478ac2, 0x939227b1d05f49ba, 0xa94c472c0089e4b4, 0x7e7a32282a0c2900, 0xe488cf88fe83acfc,
    0x31f8514dc6115cb5, 0x8c641a6cb43ae7da, 0x8b8f45b58a12e6cc, 0x3242e1de1fa494c5, 0x7dab7b373c8f551b, 0x56ab9bcf11b6f25a, 0xaa27b4380a8333ad, 0xcbf18ef2f229c025,
    0xb7d6af71fb640a75, 0x47a9f7f697a28e0b, 0x6b663188dc931a44, 0x7f404379407b0976, 0xf500974f78295571, 0xc7652177fdfae41b, 0x860bec0a6c78c5d0, 0x3178d1bb1435c9af,
    0xcd1bb864637cf4f9, 0x10e34d63f48c5ed4, 0x5b075be3c412ad03, 0xe6857f7fc3345385, 0x1ca28a8ee15f1878, 0x5d72264551d68eae, 0x581dfa7d2b4c09e3, 0x6b61903f2ba03769,
    0x2bed704f6dff2150, 0x3b66f17073149664, 0x2a722a8a3b798a66, 0x376bf9e5403eedb7, 0x95c769d2fc372cd9, 0x35698578596b792f, 0x2670a8f2e7f7a641, 0xf6f8ca3c58d3089e,
    0x47d58af32a91ddc2, 0x30abb6eab3f02921, 0x490df25e43f73f13, 0xf537773939d38a9b, 0xf9099fa3212d8fc1, 0x63ae367eb959d9f8, 0x8e2e511cce74be18, 0xbeb6132d28ff4099,
    0xc88b69c57731c07e, 0x52ed6a3d227ff763, 0x52cd70822173c59f, 0xd0d299040f1250d8, 0x5769c965f01be7a3, 0xf6db21dd26bbf942, 0x648ab14004516e12, 0xabfc349e2f1d2118,
    0x0180bb9d84d7141b, 0x134911d8e4bbaaec, 0x4b92b8f64e804905, 0x897da7bb358b6d21, 0x38ecb2e51caf0aae, 0x6543e7e5a787f93d, 0xf571032510364cd2, 0x995b4a9a20d88c89,
    0xdd379996725be125, 0xb1df2f7a4fcad9d2, 0xa7b5fa7d47457508, 0x2575c600187cec18, 0x1e259e3d752b00d1, 0x83580245568efa73, 0xed22d2e0508647f4, 0x84442dfc92fb06ff,
    0x3d24524ac4d2c465, 0x0462308a30d9d3e5, 0x45254a01baae8a2e, 0xd2593661cf6daf12, 0x5dca599abe435bf0, 0xa169da8afcb3a620, 0x6cf13824af9f6508, 0x416b602161b2bbf6,
    0x5c4b342a0ead84ed, 0x654b3a33c67ed63d, 0xa31dbd4bffd8c960, 0x2f7fa743ade7d8ef, 0x3e6c057797b29702, 0xd19f608ec8d8fdbd, 0xfc7473793f836beb, 0x3a0b20471be6e94a,
    0xec0ddc2b82cb0747, 0xdaeda7da80dde8ce, 0x98e2f9df22a96604, 0x8ab85f67eec67f06, 0xe2874ab08c6c6e2b, 0x0445b6381fc45c42, 0x53e29b91b9afd253, 0x0d90c6f4584c9d15,
    0xbcafd803c7fa407d, 0xd4a5aebc3d150787, 0xf0d92d5deb9a8696, 0x516478a2567460c7, 0xab9d905b209fb8a3, 0x0e93b2f066f5b023, 0x36ecf288427a2ed2, 0xcd8596762e7c1384,
    0x2755c80bb1316dd9, 0x787ab24d5a604fb9, 0xdf25cd6e045b914d, 0x968513d803c0a611, 0x60f9fd6e5a72901a, 0x9a31b57f2e430478, 0x893c927b9668ddd5, 0xb0992fa258261de1,
    0xf4bfcc77ea4809c9, 0xc56284e868ddcfa0, 0x6f0aea97a43907c7, 0xfbb54c148bd5828b, 0x18c1df9b3daafa9b, 0xd037d19f80bdadce, 0x06a3849d9204ccb4, 0x3ace4fd8dfca573e,
    0x35eaa6e36461d0d3, 0x17905f2a781de540, 0x2d531dd8552f2765, 0x01eeb7b6a1494475, 0xb769488b3901a9f3, 0x7460ad9d8bcceeb9, 0x66a2abf1c7753bb8, 0xabd4a0f7fac6deb4,
    0x869252402e6a9f99, 0x109e9f4b61c6f6bd, 0x20498d04f39cdf59, 0xd62fed8ce52682d6, 0x58f3f064c341c481, 0xaeb47ad53e382513, 0xe63d189ea323c1db, 0x106309c4f4f41c3b,
    0x828cc5c0f20462a9, 0x6d96e2a601b93c0e, 0x4cd09b8e39701ff1, 0xd909bb3be4c02cd8, 0x5eefa9a3ec3f9511, 0x05977fb39adacec7, 0x5bb65608aa16f24f, 0x10d8c2a3b3396bd8,
    0x4b9fdb48e73da1f4, 0xaf424d81ca4837d3, 0x12977a990acddfbc, 0x30c06b0c4ad8881a, 0xbdb45a06820f214c, 0x0d2b4dcdd1d72197, 0x6ac7be40ce1c0b24, 0xdffe969d5c0c2037,
    0xc86610f34f66b3df, 0x015c9bf09e75950a, 0xcbde1f5982ace379, 0x6a13800155ef04b7, 0x1d092851b33025b7, 0x41d95d9e42639ac6, 0x84f5b14011d026db, 0x2de1cdf12e9cb8c0,
    0x866723c1db16de4b, 0xdca3ec1ca731d89c, 0x72976afd2d0f4836, 0xb21e68780bd8ee9a, 0xaeece0bcd44dbd4b, 0x01b03b987a6324f8, 0xcef0026bcefa2aac, 0x85405981156ecd7d,
    0x123308b4a9c5711a, 0x721dd5dacce5bc3d, 0x26804860af6a7e95, 0x7ccbc3bf87cc4d54, 0x5995334c3e242616, 0x3acfb676b987c213, 0x145518b80573d4c0, 0xc6ebde08aded9af4,
    0x9a4daa72d104dd8b, 0xdde4dac3cd08710b, 0x57e470f1db64f91b, 0x6c7f036eb374832a, 0x9f07db54caab8fcf, 0xbc06cf52d8d5f56c, 0x4aea7bee9c0e0ed6, 0x282c76e18b24f8b4,
    0xcd43853968e0f8c3, 0x9cab4fb10369ef34, 0xf5aba10ba06befde, 0x99ff4d8ff311e9a0, 0xd35aaa101d22c55a, 0xf2b3182557bf0529, 0xdd523fc5310a3ecf, 0x0b3cc5a35c82a6b7,
    0x3a15c7a108af767c, 0x0693ab9cd8951ee4, 0x05f23cff908ed521, 0xba38ae4ed8f30818, 0x3567e7eb19841fbc, 0xd4f1f91388ce0fbd, 0x7b3440651da95cb5, 0x56b6c91fef0c0213,
    0x0c5516aa79811c1c, 0x8869b952943a29fc, 0xf382d60f67fcc2e2, 0xd3a606c601b5c66f, 0x0d6b519f677f9e84, 0x3ef8e988f9e9e6c0, 0x8726d00ed296c2b3, 0x16429acf62bb2d8f,
    0x858ddab4a1817e91, 0x6f0b334f51351a23, 0x7f09f1f531213b6f, 0x82a81778d373eb3a, 0xbed0e457d7a8801d, 0x632446bf2a988560, 0x3f2e4e9a57914a68, 0x45690fae01c59d44,
    0x29dc4c21401d787f, 0x5c4a52f82ad10df3, 0x7048dcd10cdece63, 0x5eee8921f4fcd342, 0x9ffe119727f734ae, 0xf39e93dc1c8b27ad, 0x73516bbad0f603e4, 0xb6b3462b6a39a55b,
    0x4a69c806e78615c2, 0xe988794843797b0c, 0xa47dcf644f700651, 0x97662389f36ce643, 0x17eef58bf866b33f, 0x5eb06c4515ff01bd, 0x328b8d67d4ae956f, 0xcd4d9449aea5cac5,
    0xcd382e53ed23ae1f, 0x7b1eb83b8306ace5, 0x15a8ecd063d726ba, 0x403b18162679c055, 0xd0a5d4ebea56f425, 0xdf882dfcffcc84bc, 0x8d61a1c805ef7074, 0xeb42ebf496a7bd69,
    0x4932828fa1eda64a, 0x9b29f654ca04e515, 0x899b922465789ef1, 0xf37e88764c7ac45c, 0x5c21a5c0dd61d736, 0x2554d8e82845136b, 0xbad57a13e441c8c8, 0xfbf59fee83ed48c0,
    0xb6dfed771b9c57aa, 0xd2a721c4ca5988de, 0x4a72eef2c3b79c4a, 0x4735ff387ce5d531, 0x6595b84458e25402, 0x9050829a6000ae69, 0x4e309f2a26856099, 0xa8ed2943cca6016f,
    0x93533941dbcc0ace, 0x841a1067098656b6, 0x30bb10f83e216e8a, 0xb4f7130dc7e9212a, 0x93ce7fc238b81921, 0x5b7e8e5a8f641f8c, 0x9ddc33deb95a5b71, 0x2f29f4a14bab0c77,
    0xfcfdd7e629b3cadf, 0x773924b26ef7247d, 0xda1da81a16bb9420, 0xd25e0cb35f1f1faa, 0xc545c1a75e458451, 0xabedaafe76dcc117, 0x429b67f6ae073a8f, 0x67295cb2e7ed1851,
    0x844c475a38b961fa, 0x355386afd494c53d, 0x81c6dcf871dd881b, 0x092af9a79f4170d1, 0x7d3dce96cbf08554, 0x72eac8accba2b32d, 0xca582b8e15cc89af, 0xc9a3d27ecf09b2f3,
    0x09acc52ed3b84f43, 0xb5b0f39553570b43, 0xe9f8c0f1152682a5, 0xdc532866d1359272, 0xa830e1dfd3792ce9, 0x6ad5e7da482f3096, 0x0c80e17dba0aaedf, 0x306cfc30b3a85aae,
    0x13970909b51d1a80, 0x14ce48989614edc1, 0xdc467497755cbd57, 0x9660670c8b61b1f5, 0x63d8896cd021a129, 0xff50d6958c5fb8d2, 0x39ee34cd34b67a5f, 0x8358e926ccc8e30d,
    0x99f8edca8af044d5, 0xd3cbf4330b841d22, 0xd174131b63b02eba, 0x38eb496124b15eeb, 0x48a22e8cfb012cfc, 0xf5da2e278065962b, 0xff4403f9200acae2, 0xf184e282b6b418f7,
    0xc6b107ca5b20c9f3, 0x26f583a441e0630a, 0x92d0e75229f427bc, 0x4f703d0de9e071bc, 0x3171ddeaace634c6, 0x12c49c6dc514680a, 0xa7002297639b4906, 0x1700f3d434b737fc,
    0xbe75a9cad6bd2300, 0x748db9d9c1cb48ba, 0xadcafa24a2f2c39b, 0xea6d56b46741bf09, 0xc30eead02da09851, 0x8577fffe20f3731e, 0x245a5b85a5e0ebf1, 0x18e5eead89732407,
    0x746075b5bfc55131, 0xba4453d3d8e14282, 0xf8a86d159d9a709d, 0xa4f4630217f0e85b, 0xf04d0d9b0b09c7c9, 0xe9669f06d6c1b268, 0xe2e27fbcfbda045e, 0xc8a35bec05eb827b,
    0xeb9d4eaae174d6f2, 0x03e09a3ad81dd4ff, 0xebda3404ab654a2f, 0x5d39c2892dfb220a, 0xf1c3399fdb7845ad, 0x7d979bb1bce205b1, 0x89d18134a93a533c, 0x35b91f56afed2092,
    0x7c42374fe8984cb6, 0x9c764897cfffdca0, 0xcaac6a4d50fade17, 0xe0ef4846a887c038, 0xd82902a52c00d995, 0xc5067a8d1a2f3a41, 0x0b4ce0b7d7daff7d, 0x9230ff23783733a8,
    0xad1951435957726a, 0x2206d08929796e05, 0xd4fe4d4127cba088, 0xa162fb5f8af4185f, 0x3427a4e96c94f67c, 0xe86e6a15f91af428, 0xb465eb367ca10566, 0xb9e3bb2376a12196,
    0xe445463326fd5391, 0xd2cb5fc8266bef82, 0x39f16938e29cf376, 0xb5e7992af43ff901, 0x4bd11a57af8b46ab, 0x0c5e337332e53a91, 0x5585aff51f34de17, 0x3324dae6ff8a7d31,
    0x7d1a4a46cbefccd9, 0x27f1086e10c87ee9, 0xc78c20aec8a5fdfe, 0x4da8bbb0f99ffecb, 0xc62e8ca1d2255a8e, 0x6888bcbdff421c66, 0x4505e94b0635a09e, 0xcd4588f38a097beb,
    0x5dd66e10fd954995, 0xf4c89fe58d2946ee, 0x9a994e3b6e6e8e23, 0xd8a26b12ea5c4d4f, 0x5ad271ccd78f3f33, 0xcc32ddea6b84a3ba, 0xe06e913d6923d4a2, 0x47d54e91bac13b53,
    0x9c284015294338fd, 0xd5e81534cce44432, 0xcbe70ca22e5c5807, 0x28449ff72f96a915, 0xdde032503e64423c, 0xf7bdbe2478c4a4d8, 0x8b7b8d331850a22f, 0x6c6d8382d09406fb,
    0xef14705131546e8c, 0xe37d671893d4f2fc, 0x5d8d444d3e8cf4ba, 0x61572c322b045a47, 0x82d10acd5f5bebce, 0xa1959df1dec34077, 0xe91ea4d68a7640f3, 0xe3b511c42ceef515,
    0x481f41613b55ec09, 0xcfc60e29aa074743, 0x58d29712da50cb69, 0x9912f2f0ae0595ac, 0x43196eb35d95b713, 0x76e6a7ee0eb0d7f7, 0xa63822a6684c88ec, 0x308d561a3f241d0e,
    0xc044c871fa3ba783, 0x37dae2451b0fed32, 0xcfcc32d3fcaf9df7, 0x8363e2ee5e5c4c5c, 0xf7ed72d0656c9949, 0xdc3b5a0fe7c9306a, 0x1c69661627293531, 0x9efda4aa036202c1,
    0x062de907d0953ad0, 0xf8041e0c6f8a9ecc, 0x6115b8f3de7a86b0, 0x347ddd33f2a2a793, 0x8e7bcacc36680035, 0x9fa94d3cdc8750a8, 0x04e8b20daa55606e, 0x5a2280dbdb9b3752,
    0x6e31484dbd771d0e, 0xa5fc6ff489cfc13e, 0xb169aadf11e60e81, 0x2837c25fdadc2e26, 0xf2030f4225a85995, 0x7807147e3e464e77, 0xf99091981e6bac0a, 0xc3723f3fc316243d,
    0x2741ab72959580d9, 0x1cb62f04ad353b13, 0xd083375dc8f7410b, 0xaed46d363137584e, 0xa3d1bb4c8eb5d8f2, 0x830282b1dc1d81a1, 0x083108d71d52fa0d, 0x3b0d22596a1813ae,
    0x4267a218068f0d8e, 0x0ad610f0ff4c2d83, 0xa8c734baf1d3ad11, 0xec1fbdf9e74e9729, 0x776d76940e9089f7, 0x423ce1f3edd46634, 0x47826701c68b519b, 0x3eedfd07b9887154,
    0x68ef1d10a42f776a, 0x6386fcab69688add, 0x36a5dd89d191c3cb, 0x8c4881e5d7393294, 0x66def5145491bd99, 0x0a91c1fa773c3457, 0x43799ffb08efb028, 0x85cdcfb669092acb,
    0x7f4fc84c4030cbfb, 0x72269f3f2b240663, 0x2fbdd32ac29920a7, 0xbdc4d61a0367ef71, 0xaa1216a122a659a2, 0xab1da8335c171bb0, 0x3ca0d22c3b3e45c4, 0x0f946baaadeae8d8,
    0xef14e81fdd2b364f, 0x2f55ada2ae0de459, 0x940af90140a2de69, 0xc7e75e9aabf401bc, 0x47a9ff788e1c3a3a, 0x2ce3f69491e5dce8, 0x81dbf7dde0977adc, 0x42ba0b11851f6dd9,
    0x1b4edf339840cf0e, 0xad8ff5b21132fd4f, 0xd5e31a8a588a6101, 0x1661c89b16294868, 0x8019be652e5068b1, 0xd91b1fada5f73c41, 0x283898bb911395dd, 0x06ba3fad70685b96,
    0xdefeb106c49760ae, 0xdad52aa98d5e77f0, 0x0b9e3af9140b5ea4, 0x6ea78774ca7519f2, 0xcb4aa4498abb9d51, 0xa5c5b3f4d0469271, 0x397aadf70746ccb3, 0xc624e8dffabcc782,
    0xcfdc959047b20f62, 0x6839796b357d0be1, 0x2c431e27f83005b7, 0x0569f1c4a75037ca, 0x709460772e4c876a, 0xeaa568fd7c9f7dd9, 0x4eae8ce3c8dd9b61, 0x8847a12643e7a6f3,
    0x50337833e84a623a, 0x6d0f0e64adf10b27, 0xf3029bda34083597, 0x8204c4bb5cc07376, 0x5eb6dc8d28db1c54, 0x08f42a900ba5d9db, 0x90744ed74b2b207d, 0x1e9991f233d884f0,
    0xaf5ca8e8bfa880e6, 0xfa43aab6924390d1, 0x4a7d2a178fc16736, 0x5a4aa3bf0525ff25, 0x00092c75b19c8544, 0x31fb7664db32f0ef, 0x196515334ea72250, 0x053efa8bfc39562f,
    0x9bf9efc1b0242cb9, 0xfdd1f568ad88cea0, 0x5bd701ea2ded6b29, 0xe3ffd2783b7121e1, 0x6301c5c26b454d79, 0xc4d21c15e28fe4f0, 0xa2a4b664ef38802e, 0x7e23d698181dfdd3,
    0x2a76ce3fcc775c7e, 0xbcf7808774f52159, 0x080f9528ffbf916c, 0x885bebd0441de6f0, 0x51e6593154e91061, 0xe5233d5e7b348535, 0x473b3b3f184aa822, 0x21151e7b977aaa95,
    0xde51ba8cbee9bd99, 0xae5f23f269f957cd, 0x708d74a0a5a682c7, 0x91097071cb646e5e, 0x3bc35e10f5963bbc, 0xb426789ae226b25e, 0xef6cad6c7f12beb6, 0xeab10ec96bacab69,
    0x23f3533bb1ac8e06, 0x8a6724bfaa07e6b3, 0x7b8760a2905deae8, 0x56702de289f4e2f0, 0xdada3f65d4f55bf8, 0x7f8c6d057d31d642, 0xc9b00abdc8495650, 0x1c51e60abc0eccd2,
    0xfec65ffbf9c42481, 0x22e8c26bb26384db, 0x6be43bc89cf09d40, 0xbd6c96655fcfe6a2, 0xb626341c04311030, 0x905fe7ef57925046, 0x9509529bde2ef3df, 0x7948636bc0cdc7a4,
    0xc30c108a100fec81, 0x6221aa9d592e8828, 0xf3c8215591cebb72, 0xd8bf6ea39c57b9dc, 0x1d183b59164b8c40, 0x7ea2a786319e78a6, 0xc973b32e93bc2f87, 0x9025624014782cbe,
    0xbd6e444a134eac53, 0xfe0f19b444f2e570, 0xf60bc3c21500767c, 0xa8502a4bd10e123e, 0xded8e57012f4651f, 0xaeb1b9241eb04d7a, 0xd513f05f555fed42, 0xfa0c380af507ac6a,
    0x65b433a8dfb5ce3d, 0x98999ef103eca182, 0xf56d0853313c64ec, 0x3e0417206422ad1b, 0xed5571f713fb7ed3, 0x02876cabef2d641d, 0x60cabfa0f8547278, 0x63a185e898896c4a,
    0x0e1ecd9e46466a47, 0xd757ae92795b1541, 0xd9dcd23ac5c15de8, 0x3b3de05121ff3a36, 0xa11606102e19c39b, 0xd6106c43e6eb5c91, 0x5ab4cccacefee53a, 0x007b8326ebd1926d,
    0x32ba940140487c6d, 0x46e0755a22260568, 0x7790f1c8c0222f19, 0xb2bb4be2c6bded6f, 0x175f675d63cdbf6e, 0xa1809a9af4da899a, 0xf7138f89ad5d7afb, 0x761b3fb67fd8c602,
    0xa2eca2c4334f453b, 0xf64d9dc500a7a507, 0x924adebceb539c8a, 0xc209a7edb19c905e, 0x6dbbff18fdc777c1, 0x17fd5c2997f84b5a, 0x73c3bbc097fbb941, 0xf67681a6300cb02c,
    0x5dcfafe1b79d21f7, 0x7d4217fb0d2f24bc, 0x53cc4b66d1bf5b67, 0x8512234b09a632ee, 0x7afef5d3c566680a, 0xcc16073d5ac4919b, 0x8cc1c7b68bbc832d, 0x50c43f4413c4c58c,
    0x724c733a800256f2, 0xff3978a5dbd4f083, 0x9b2a00ed5c8a3916, 0x69e19793abf7a632, 0xcecb6edcab1857af, 0xa462893d3c564a29, 0x61c82e8a6cd57f10, 0x3fa79f6ccffe83c8,
    0x364ce350ccad2815, 0x83d7adbfcaf46f89, 0x4c2fd40ac0ad5ce2, 0xd51c2c33a7b276b2, 0x37328b5094395ce3, 0x70812a15ff5243fe, 0x15ad4a85db620d26, 0xff3f9978e53508fc,
    0x4dbe3930f085dd46, 0xe68954afa8bc18b9, 0x1e20699412fc97b3, 0x2b5bc43566c8182b, 0xe948a5e26d1d3ddc, 0xa35730ae4e899f73, 0x8187e151ade21342, 0x22ddbfb842707e88,
    0x314b8155d6b6ad5b, 0x73d0d75407a752cb, 0xd9da783ff9fa2b9d, 0xf435d414df4f5076, 0x1dff839d5c16d42b, 0xd136dc23e40ab6c1, 0xfca6360f0e1c5a33, 0xaf1c58598e7cb56e,
    0x43dcc5d73e585d51, 0x519f6ad4eebd062b, 0x80754ac3c1d740f1, 0xaf1fe551463c5b67, 0x1d24556ff8ace198, 0x02b91a2134d2ee23, 0x13d1ffba18d54997, 0x5d56aaa246770a3d,
    0x4fbbcd60cdb5494b, 0x848f8dffabbea9b6, 0x42672e40d5a53819, 0x584f13fbeaca5bf3, 0xf160a9ccab6e11b4, 0x51a73a3a653b6373, 0x63c3bc25ecdf58c7, 0x325cc030e9514373,
    0xe2a6b8f7aa1916bf, 0x9c668a4c33a54663, 0x5931972834a653b2, 0xc5e8ca195ea0274e, 0xa5a7a5e95eabfb91, 0xdd71f31da6f7c46e, 0x51b21e140a5fcb76, 0x7d4dc704d3c881db,
    0x72bb35a49a20c914, 0x1c426d0b4fe64fef, 0xecfeeaed431bab4b, 0x85ac16eb56493abb, 0x45c61bdd78abbe40, 0x937b96bb7431209a, 0xaccf7f070abbe8fb, 0xa17a2586c5bab868,
    0x0b40d7846acd93bd, 0xe92a3100a8aa7d86, 0x5a90c85c2b95d141, 0x42b957edf0eac80b, 0x97b291bad89c9cf3, 0x8164c5fc56ad0b3c, 0xe178efd995023ccd, 0x0035cde42dc2cf15,
    0x6a755592839eaf7a, 0x324a4b4eba667d1a, 0xf5c3460b16ba21a4, 0xde9f478017f5ef6b, 0x8d31bc90b58a334a, 0x31fbdfe21dc8eb9c, 0x23d8b2d4a678ac83, 0x4dbb4cad0a7e2706,
    0x7c91dba2fa129d98, 0x213e75991c59be79, 0x59f768c230bde513, 0x8c2972d5ff12ff22, 0xc691e275dd7475c9, 0x25f4ac9004ef9825, 0xfaad8de2af3a5b1a, 0x0460afdc2ee1ae1c,
    0x8f542a7f1830047a, 0x2d9c80739c120316, 0x259137908d220bb6, 0xc1f1ed239eb2e2d6, 0x52fc97633cb4e187, 0x466c94626a15b643, 0x4a2391acbad2fc28, 0xd85fcc762fbee484,
    0xe746df69c444e173, 0xe716b7df6ff3866f, 0xde7f692c0021274f, 0xb5ff42f5c63a693a, 0x183370004c000aa6, 0xcbb94a5f3fd9d41a, 0x592117ec50ae9cf2, 0xba6d987fe545a9d9,
    0x7f564fc0813b5d4d, 0xb0c3c5252443ec98, 0xf763d3b20ef393ef, 0x86ba065985aab176, 0x1089bea456d640dc, 0x572ab615149aaddc, 0xbb18497c0b5e8699, 0x42acc8ecf1858fd0,
    0xc7033a8ea70569dd, 0xf6670a5251e942ca, 0x76f01cc756a45ce9, 0x12192f6c25bb90b7, 0x5e67d8c073397f3e, 0x5943d66bca82b331, 0x2177d44402e76b82, 0x1e247b0fb5819ef9,
    0x69f15537f160c9db, 0x2b7b74de9915f35c, 0xb028cd637d5f3b3f, 0x730cac8955b4a829, 0xff62e2a27178e739, 0xd895fd5a4574f298, 0x9245177f0510e27b, 0xf5d500feda9a7127,
    0x073a60f73af7d8b2, 0x36fc50273862bdbb, 0xcf8391afee8b886a, 0xcd304e07207e8fd6, 0xf71260f3d5316697, 0xe8d71e81ffa497c1, 0xa945c9b42720abae, 0x45e5de0e5987e1ad,
    0xce05418c9fdb0589, 0x94a780beb0eda9d8, 0x5b7ded5404d3fa8c, 0xdbe264a2ee1ad880, 0x7aebcd67079987f5, 0xf60062c177a57277, 0x9f71be1267cec822, 0x3f901c7848bef8e0,
    0xecebbadd7dbef974, 0x3d01a5999ab31878, 0x9646807f6f1f91ba, 0xd8b30022c4e5f774, 0xd4f845b74984a74a, 0x9ef317840a4cd193, 0x201c39b8e0cbedc6, 0x19204c0d6c7fab92,
    0x2aff1d698b3e9596, 0x03c3310096cbfdfd, 0x37fb5e89e4ade4a1, 0x73fd021127db2008, 0x1e56cc63984cbbdf, 0x884aa70a81db42e6, 0x2230ad7167d0a7ee, 0x6eac311bf6f3a5af,
    0xa6bb02fdb15ad981, 0xd53d933ff264dba9, 0xa46551cb65cfac45, 0x666c41a76471a819, 0x7bd7ba38a851312a, 0x480fa8cd7fa30feb, 0xa5c42ef922662d51, 0x0afa1c9a8be1ab4f,
    0x8d9c9aa214346d55, 0x516094082cdc3e18, 0x16a963ea107997d4, 0x8280001138c15cfc, 0xe4ab234bb9ff258d, 0x69880d3b6699086d, 0x3d7d3d1e32308eca, 0xbed0774a3daa1b2e,
    0xb6df4485983a76d4, 0xc6fb7d520aee753e, 0xdb74f71648c81d1f, 0xb88725df36319c29, 0x9d0c477978210a58, 0x841060a628470c02, 0x70ccd8bc370e425c, 0x1634e628b865cc42,
    0x0e037ed34a49d063, 0x53cdc28cf90ff0e6, 0x348b5047fc84dcbc, 0xf79591be4e039c0b, 0x9e5db80c33f78fb6, 0x69ce92f11c21829d, 0x919dc94a46942844, 0x0d8185a00b9273ca,
    0xbb19136e4077238d, 0xdd9d4ca7441d8075, 0xd51e8bfd157c3dca, 0xcefba865bb345540, 0x89564e91dd8456bc, 0x1029166c5b13d782, 0xe02cd50a812d2c44, 0x654de0c9dadd2e89,
    0x14709b5a9e1a3379, 0xff2a7b2dc49a6ce6, 0x93bb630b0c412bd8, 0x11f4f036687dd7c0, 0xee7fad8f341b1c8f, 0xaf83447eca86634e, 0xbd9c1795dc812ce4, 0xb7099de7e683f6bc,
    0x2d39ca5fc097f911, 0xfdff3a8358576b7a, 0x272beaee1c8f9796, 0x726e78ffdbc59ca0, 0xb67d5853eaa0c878, 0xc03a497efc478336, 0xdc72b0f36a94a20f, 0x15d177b6ad45123a,
    0xb887bb864c795fb3, 0x6566180c005efe01, 0xb3b53dc1f6851821, 0x44699e38ee0a6581, 0x1c55a93806333642, 0x1fcbc68cd58d1cd6, 0xa244bb60d708e219, 0x07173dff1b5350f7,
    0xb8715e9116baeff0, 0xd3752ba762ba2ca1, 0x86d91965e5a31a56, 0x3c27c4951d076d17, 0xd41f651c2ade59ba, 0x8f2ca8db21b97bc5, 0x1c2a1efdae15b528, 0x96977c9dcdba8c3a,
    0x91c8ddf3688697af, 0xc2de47e16a2fa935, 0x01d09ee453aeaf90, 0x9dbc205a2b000616, 0xc7a82e96d594c62e, 0x3317b8eb5b8b73e5, 0xfff7c8b4c3a32096, 0x6453b70094e3358c,
    0x2b1bae699aff8a4e, 0xbf7b4736ad753b49, 0x20f6e0752f5bfc7b, 0x497dd9715e1cd5d4, 0xa91030923e88ceb4, 0x602ac3f33ced7c4c, 0xbf584ae8dfb8e2d9, 0x3105b41ec3549b6f,
    0x163d3abbe998423f, 0x51234aac25187982, 0x8770f9bcfe97c132, 0x1800daeee2fe2a88, 0x0f02b3a8243fd4aa, 0x4a536e070e2bc9ae, 0x628c64308bc9c315, 0xfbecf1323c9722d9,
    0x331ad785fc3e1d41, 0x5f5508bdfb62937d, 0x91a3214706923e0c, 0xfc796e8da1017f42, 0xaafe90f59343d9bc, 0x2d136e33a60bef49, 0x02f9f2c3db9d0229, 0xd4892cd932be8419,
    0x79c72ac302f0d281, 0x8abb8e35b1d94786, 0x0c6de808c0c12a8d, 0xac6d4d8e5b9c2ed0, 0xcba0baa1708e791d, 0x4bec127f651f20ff, 0x261d3b5a50d67450, 0x0fc781b9f92cd6c3,
    0x383faf53f2a71eb8, 0x0c20e971447ba60d, 0x3bdbd7533c088d5b, 0x56c8661b6d330584, 0xb60ad35ea1d2263f, 0x737d7418bce8ebe2, 0xdda539ab99ec21ed, 0xe5c1cea1abbce298,
    0x4c92449387476985, 0x9c3be4e72e40685f, 0xf6d9c228a9f85902, 0xa44764c91adc6a9a, 0x0db0d2ba599a7553, 0xe3788aa1dd74946a, 0xd239baffacd81b2e, 0xef52f85666c340f8,
    0xaaadb6ea9b1c8a45, 0x86fc426284837b81, 0xb33810a5001fa2cf, 0xf990bd17f7e2ecf7, 0x14aa4676275e6c1c, 0xf19a05d12146d05e, 0xea5f3c7c6d5b9b4f, 0x32efb45c62042da0,
    0x7f430093a67ce3ea, 0xc8f47792c4d16d4a, 0xa7e72976b7f5e237, 0x26550333603f8d3e, 0x9b8fe810f3c3b225, 0x65e904778694f5c3, 0xe18bde37757c008c, 0x4fc064ba9ccda596,
    0xa6ec138b14e30506, 0x064b8d8f63af9202, 0xc3783b153f753ecd, 0x20315c3032141460, 0xbe04af9758a4cb35, 0xa7f4476ceb2653a3, 0xc4699159169fac3b, 0x4e2d709e9b1d01cd,
    0x4ec5972ace479262, 0x2fc417acdf559f30, 0x0605a730b11000e5, 0x8b65acbb6a17e365, 0xd967fbe917266184, 0x1c10125e01f5db0a, 0xbf638c23b61967f9, 0x71b359fac654beb9,
    0x9d83451d64277002, 0xc8777ce755abe4f8, 0xfb4530585d7e824a, 0x63c28165d9737d56, 0x7d9dbb4c39824fe3, 0x469e8165902bacf8, 0x5fad83c408ef9c40, 0xf8b2d576c30d1026,
    0x29f9f4bea44b1781, 0xac726909624bfe7c, 0xaafd751738177909, 0x90563245ba1c612c, 0x389ec2a7d7e59ce3, 0x50500c567966d3c3, 0x26b15bf6cb1ad6cc, 0xe9080fe122c631b5,
    0x17f6dabe12e3e5d3, 0xc3f85d05a0f070f8, 0x67d33630af152ed4, 0xdb3b4096c5c332d7, 0xc3dd07768e70b774, 0xa1e0b82d0516b75c, 0x867ca995ad903a61, 0x4fcd47a488ba6d51,
    0x6c6aba39dfc7d00e, 0xab65e0c18b16269b, 0x09ba717e85654122, 0x07e4cb761fb1b0e5, 0x9265799c5d55a837, 0xf7e6d513b6437316, 0x94a696b3988e41e6, 0x2607761bf2629a5f,
    0x973e75d9df82ece9, 0x48730461eb3c4d75, 0x5796dc273ed9d51a, 0xf325bafd97b61151, 0x7007d37e9b53ea4c, 0x3368fe5e05f94087, 0xadd778da036b0736, 0xc31fcbabf6fdf8d7,
    0x35de52e719187698, 0x1d2f3e4087fa3c08, 0x8047f5eb6ee05190, 0xd5add1eda45df387, 0xc2431d8a98a8fe49, 0xb1c0388fa3162e61, 0x1f0ab07565c55677, 0x7f3b14c57417b083,
    0x1f0ffa4f1abb4291, 0xdfec55dc328de4d0, 0xb792695f0a121172, 0xe684ea8df0457fae, 0xcef58a827a97e9ba, 0xfd341be16fb9e359, 0xc87a2331a9fb1692, 0x2527b948cee2e7e3,
    0x5e101fbe7514323e, 0x0d06560293e73c10, 0x1829f79b98724d80, 0x0c6ea39a34167a64, 0x1da654dac1c2b486, 0x4381d7a197d73b93, 0xed2de677dfea2660, 0x98cf929f0489101c,
    0xd6f382504a8d8ea7, 0x483110e79c14ef66, 0xce485d95bbc34776, 0xaec1a6a8430e7289, 0xcafe578fb670a41a, 0x61243b580f10d832, 0x221c3043ce630b2f, 0x8e8705368c784121,
    0x7963cf963518f155, 0xc21b75f27e48406f, 0x8f2f2bb31db2a418, 0x467a4ce355531acb, 0xd45bfce4db6ad410, 0x116a3d9dbd9162db, 0x26b549e62d30c113, 0xb4799b40daeb1ca5,
    0xac6d4450ef27b16a, 0x51303f5d166ed3ae, 0x2a7b47acf0255aef, 0x85c10733b0fd7de5, 0xfa1b80f6fcd647ba, 0xc3b3a75c8e36ba96, 0xb89f7cf587c773bb, 0x2585e4ca847ec1e1,
    0x8f587f5b9b828303, 0xdaf3e553b32110ee, 0x5a080e99f299f28b, 0x60b02561cbf056d9, 0x819439e181a81c62, 0x68e7551c7255e324, 0x8e47a1bdf4e2642f, 0x30b7c9517b5baffe,
    0x2effcd65da6cf6e5, 0xc0e53b063106b643, 0xd1ac9588459392bf, 0xc3a9b3fe5c4914b8, 0x6fd4a4e70d53afbc, 0xb16f9f98ee51d7d6, 0xc372f1f76b65fc1c, 0x7ace9609a780c6dc,
    0x4b62ba7528b34440, 0xba37cf920321a2ec, 0xdab82152af4d36ec, 0x359da66c3e405aa0, 0x32133b6e7e57f6b4, 0xfb739dd61168c5ee, 0xfbfc045b30bf74a2, 0xc1c2002bb95c9009,
    0xfb0e87292c13de33, 0xe6a1ada23c8a0b87, 0x4a4ad963b5c4b22f, 0xed9800b5e15d4c3f, 0x1d3fd890d8ae7729, 0x46aa7d9d9bae01b2, 0x4f6e3a19e1a8fb67, 0x2b460d0337d72c74,
    0x7be622092baae6c5, 0x8949c3aeda3c2feb, 0xa9d884a9e4704860, 0xfd3dd63e0fd6e075, 0x5de1715bbc8b024c, 0xaebb8f1195f7516c, 0x3bd0bf7a3f4a5378, 0xddd22dd5c8597960,
    0x94e9199dc8d209b4, 0x5de530f34523777b, 0x51ba8ba0b866a17e, 0xfd55a04a1d22b19c, 0xcdb238bd4130d0d6, 0xa06aeb43357757f5, 0xa475cc0cc62d4527, 0x6d0e779b6e6a8758,
    0x713405fae15e9778, 0x0f00a2b27568a6a3, 0x62bd58efbe3090fb, 0xf05cdf4c267eb1b6, 0x5e62d04738221b8e, 0xf5b9900f1295612f, 0xa0e5749d177233cf, 0xc44c5592311f8054,
    0xbd52eb6cdf769fe2, 0xdd0d254454cf2122, 0xb981221ff70b0658, 0x3c36fb55ff496fd5, 0xf430a57f99390967, 0x0954ace551e02989, 0xaafe4ec82b2d9387, 0x6d9fb14548a4f4bc,
    0x8031a9996ef12134, 0xf6416c9d68835bd2, 0xaffdc09d53a51a0c, 0x19ecea50392e51e3, 0x34a13752a3b17634, 0xee74fe197f0a21c7, 0x428f82d78e4fdbf6, 0x43d9a86b4ee32b41,
    0x37bcb35d71d05a42, 0x6f9295c16c0084c8, 0x83be0ff5413d3a04, 0x3cd1cc1bba243b00, 0x9a355c5fe780c65d, 0x96f751125aa49305, 0x4996cbc8f7336602, 0x0c35ae189a910bda,
    0x17aa114cd1e76239, 0x3b9a332aabe8563a, 0xe1275ec7a3241720, 0x7725b43f265d42a2, 0x652de643921dc113, 0x95074114a43d3ba2, 0x6ac46e80d122a80f, 0x1af28df0f5ddb5d8,
    0xc49b4fcafd637609, 0x60812edd2d354b6f, 0x3491bbfbc599c6e0, 0xfc5c0fada9da1453, 0xb9d457569b43643a, 0x70ba805435dffd85, 0x128cc37ce3a2d1e3, 0xa5e7f2845bf10011,
    0x5a9599124872a087, 0x6358b4f5deaff08f, 0x2d11e3e6dc803a0d, 0xe028f2b88218e837, 0x0f71a38a839a4b4b, 0xc92a5c359039daaf, 0xb2cc835b6228f5db, 0x8ae04d563cbc4d7a,
    0x1c1cac7a75e61830, 0xfd2fd5f227d0984a, 0xaa90ea33113594e1, 0xf9e02ffebbe576ff, 0x5ce891014479b80c, 0x605419be299f8523, 0x83202fb7a4ae2a75, 0xf6e64ff96707e5d7,
    0x3ccaf13d7dd066ce, 0x01aac585c5b5e009, 0x1b4aab8014566d6e, 0x11e7198efab59ba3, 0x24a323f70fc7120c, 0x5609b08316141155, 0x98b0a7b806547c85, 0xaca41a2e51149415,
    0xcf751f8bd38bf1f5, 0x58ccdf65c8344efe, 0x6c72df390c015ec8, 0x133f9c9c23306d85, 0x61d1cfe15b558202, 0x6a3c4c3582a5f673, 0x637f9512f4c797a7, 0xd330644463579ff0,
    0xf16e1e34b4ee7ea3, 0x618000e4502dc31c, 0xaa71c457381d0335, 0xf8d920561946d767, 0x9cecf035b94a3d40, 0x3e4545a17b61d5d5, 0x1c3564aa53e6e73f, 0xc2f4bd3857b00d4b,
    0x211858b81239b300, 0x5e4926ac16c86f0a, 0xe83e64adca66d4c2, 0x63f875c830616302, 0xc6d8069d2b091649, 0x92f747c0d271c5eb, 0x39fa58b367129527, 0x4984ea9b3a80ff9d,
    0x354da29136527160, 0x997edad9709c86fc, 0xad497e23b94da9bf, 0x7d12cc94bd4d5b76, 0xcabccf6f82027a0d, 0xed6559dcebfc6c95, 0x2f81892df9e2941b, 0x83c3531b95bc842b,
    0xe48a4ee1f58654e0, 0x05fdbf72d0daa87b, 0x51ad2decf57851ea, 0xd61ba55be8f651a5, 0xceed919f6700c3e6, 0x763257403bff52ef, 0x61af8a4943b1a111, 0xddaf8c619a405fef,
    0xd722bc84759b7dea, 0x35e5a14698bb02c2, 0xadcf17d7252bb6e3, 0xffe831ce375687b0, 0x02a7b4f8dba11145, 0xd4e67ff0a1cc75bd, 0xf6bed864cb3c0f74, 0xe379cc57b232b594,
    0xb6599ef34e3d74df, 0xd06b61e56f72748b, 0x2ad1cf0c57a4d409, 0x98afe437bbe1e3aa, 0x1e21f20f87f1dcfb, 0xaaf3d2c81546a6f4, 0x7d14ff98c8a0d395, 0x3664b61f266003a0,
    0x707b3ab273ddc773, 0xbb486f128f8ecd85, 0x7a396e34185f08f6, 0xa9d40d14282ef537, 0xad0fa6ce1e0d0138, 0x990146e8ced1b2ef, 0xb73509ea936fd5e5, 0x8408168b79b481aa,
    0x9217fc8086230dd9, 0xaf81fa1a7a00519d, 0xd3c65b61ac9d8d7d, 0x3e83ff6d216d466a, 0x6393d00840e8fe0b, 0x5195eff7a58ecd18, 0x7b7aabcecde2f2bb, 0x1553aee7976dbbb9,
    0x5d7f749ca175d496, 0x6292f95e5d333f51, 0xffe7f74bb8baf5a7, 0xe9649e0679728c39, 0xa937ccfa06522d38, 0xa7495d7e37c3a928, 0x974158e812ddc092, 0x9a6e70c82ca0b636,
    0x4ba73f678b2d9ba1, 0x752ba57f558e6a5d, 0x9586e2990a7af7b4, 0xa486d8ada4ae89fd, 0x15ba224f45406dcb, 0x5854cc00ca213240, 0x12cd7a5d7053add0, 0x960b6b398a21e899,
    0xac81ded4ec6e91d1, 0xe148de8034d93ae0, 0x3084579bb0d44847, 0xdb718742421f4cc0, 0x7358c2d19a2d549a, 0x929c1c9f9de2d932, 0x269b4d558077ce0b, 0x25fcf5912e113dc7,
    0x04cc755f9b71f92b, 0x54069e1f886a4974, 0x5789c6348dc58a5a, 0x1dd27d9819361398, 0x7a2c2390a9dead06, 0x836b38bd06ad26e8, 0x735114cacf0abb97, 0x4ecfb2f5999e82c0,
    0x85cd7efe9da98029, 0x88e472a38d18b4ce, 0x6e0a3ee3d8777812, 0xa05e44ebb1425ce7, 0xeb884cca4ee53297, 0x67a0f982cb5689e9, 0x84fee0ff278b4fa9, 0xa002601e44d5e266,
    0x95fa98bbdae12807, 0x118c212dbb88133f, 0x9ede913100051a91, 0xd354ec4f9b29f406, 0x032ab62fc51a4ed6, 0xbfa91cfd68c85311, 0xfb98f0ef27647507, 0x5e418f8926b631ad,
    0xc17e3e4fee8c4e5a, 0xc221a1b7acf82d68, 0x67bc9540ebff48f4, 0x390b760628e7982d, 0x0d9a4b18c65ca2ac, 0xe27166e392c64490, 0x081ae367a842acde, 0xa041f47bfe8bde53,
    0x4992b5f7f17e54af, 0x99c4a493193d843c, 0x932846bd07cfbaba, 0x1de956fd8e865a43, 0xeba2f84cbff126af, 0xfc5a5703ac806638, 0x47cbc2aece2dfa99, 0x20cbbf78bd8d99e2,
    0x22f23b1804c21205, 0x401b1e0887941f00, 0x4421d0c0c7631a72, 0xb7cdbc7b4156fde4, 0x61fce30f2abd51d0, 0xbc70fa9f22178665, 0x94516d4d06878320, 0xfb4a042f53e53e96,
    0x34e40b1d511804ac, 0x22f37391e01602d1, 0xc280b1aa78edf92d, 0x0efbce19d6a90f10, 0x2bd9185734d40dcc, 0x213d47ac1e778360, 0xc63af769b6d25114, 0x13232c903e39fab3,
    0xb6757d5b86fd514f, 0x1a6dd98096301f47, 0x18bab6a726908647, 0x05d536ca761feda8, 0x15bff4d2b834d102, 0x0ddc2d840252dd3a, 0x766542ad05502aff, 0x109015445ce703d5,
    0xae20cb8c3d9dfea0, 0x46c095b0284fdcde, 0x2aec0ae73dbf67c3, 0x85bd72390c54277b, 0x85d589367f593a03, 0x8c18f9bb056fff2e, 0xfa2e3c913319abe9, 0x9ff6e4cd79254ae9,
    0x03fc24efd2f3d4b4, 0xb2706372e82111fb, 0x097721ba480b1e14, 0x9e06c158cd3746a9, 0x683ec04d3612e0bb, 0xed3a15599cbe3da5, 0x807d052bd2d5260c, 0xdd923767b4122b7b,
    0xd186423ef1afb4c9, 0x22ac6c53b4c862e1, 0x13da7b1fca53e5df, 0xdd5251565fab22e4, 0xa1197271cface62f, 0xc877adf578cd19a2, 0xee960066597841bd, 0x366359a40c773e2d,
    0xaeabb0a3600f13fd, 0xabebe74e161a2d18, 0xd71b9e26fe2b124d, 0xc4662e6e1f313619, 0xfe173a50c65e8caf, 0x1bec45186302f028, 0xc075ff623f3bb554, 0x4323d08715ed7717,
    0xbb776e2356075217, 0x1de047b5503e9641, 0x2e1bae289a76bdd7, 0xa757dc4e78636ced, 0x1095069123a4d1f9, 0x3f14e9b797008cda, 0xec63848d50b81ff9, 0xaf3b5cad36a95559,
    0x233f53e5cf01a158, 0x5c8d2abb26b8dcce, 0x6d7537e21ef21ad0, 0x3c97225a9782d11a, 0xa6d3757ad819677a, 0xbb1692af9785433d, 0xd185a54d16cc6631, 0x39a85ac7b47d54d7,
    0xb1a3cc96aa01e9b6, 0x8e7379d626c41f79, 0xde4e39bf11f63063, 0x3583d9a70f56bdd6, 0x4a41104b4edc1f13, 0xb32372a1e2403d80, 0x24f4942ad83baa34, 0x851fed6fc80a5dab,
    0xcf66b12331d0de29, 0xd29c8987a3759f4f, 0xb724eca99bd71bd8, 0x998eed25e5462fd7, 0x18cc0667b23ed309, 0xa1678d75c0f9970e, 0x0e94c4407c882ebc, 0xaff49c696b108ff0,
    0x8b85dc03cf67af83, 0xc3b8971a2c053ba2, 0x51b58872e31237dd, 0x270d8a4bdac2c029, 0x592315a7ffdee7ab, 0x6f9616538e5248cb, 0xd3852c3c412ced71, 0x627199cb4cea1797,
    0xcce13b89571aae9a, 0x6d89ba4fb0251209, 0x1c9f50ab6c243e6b, 0x8aa0b93b2dc1383c, 0x7f548b6e1f79e9ab, 0x0cebfb32a3be244f, 0x017d1af1793fd3cd, 0x00ff6670e1a38c31,
    0x36eed14d0e34adc7, 0x3abe441ae4f2a164, 0xb72d2b9e2fb7d8d3, 0x9da2accc7a9055af, 0x97d125518e51fa97, 0x99c34b9a44826d1f, 0x4f4076a28ddf9638, 0xf9c53f64cc369d29,
    0x511e0048328995c1, 0xa88a11c39be88ceb, 0x2cf0f489fdd207e5, 0x9340574aef831f56, 0x804be4f3f31293ea, 0xbb4faf64c2a79175, 0x7e1b92775f22058c, 0x64ddc9fad2caaf6a,
    0x0cc102dd78d54fcb, 0x75420b65bd9076d6, 0x43ad0f0faf4e6657, 0x7b7be9498e27286c, 0x28ebea8ca428e47f, 0xb8261eee41c26b60, 0xfb9699617411b1bf, 0xb2f5a238c8e024f6,
    0x7e6243e5c35f8bd3, 0x9d8a370c1d4933d7, 0xf90035f232f83b9d, 0xde869941089e4792, 0xbb56c69fc5e94c5d, 0x3c20a31cb2acfee3, 0xec681c5669d1aed4, 0x35f813bbbd63efc8,
    0x230bf3de5360fa81, 0x019ca9307351b1ea, 0x89483d5f294ad0d1, 0x2d26d5c3523a7bb0, 0xf448b3a734829026, 0xea966ac84c0d84a0, 0xbbc75b0df9cb45b3, 0x223fc92dd877705e,
    0x82116ddf8aa5f946, 0xd833740e0435e67f, 0x3dd62d9029b2c9b5, 0x9d586c02e7d84980, 0x053549bc36234aa6, 0xb714a37694615d34, 0x310fe9eeb979f658, 0x49195c1ebd4390dd,
    0xf8eca25389e4ad62, 0x3c0aec86657896d5, 0xb4ff852a39a579ed, 0x746e85d2c5b681b8, 0xa79919f1fed354ee, 0x3b5af8c711d7552e, 0x2ad734a81d085256, 0xace41048241012e7,
    0x136b210fcacc5cba, 0x9030ac05d3bc5ef7, 0xae4581e0662ea88a, 0x9dab74fde9f5e395, 0x97c99675e85ca95b, 0xa6daedb7fba8027a, 0x627efe55a1a9d222, 0xa1ca5bf7d9bdb3b2,
    0x7f9a4f4ff38af6a5, 0xe6daaa3132c047e9, 0x8ed319a4c49017d8, 0xdecec69b23dde41c, 0x6252770bd96b69b8, 0x57a7550df92a1734, 0xa515e7cc2adc773d, 0x4a0275ace8116020,
    0x8d457d4f899101da, 0xab405c20ee2cc2e7, 0x3dc8c539033cc8f8, 0x1722b2c04c0bdb46, 0xa5e9648b2dacd730, 0x7034710480a5bd9a, 0x7eac55fe42fbd17d, 0x09289386d2f4082b,
    0xd1a2f0078ce8def6, 0x1242812623174229, 0x08599f664d91c228, 0xc81c406a7396224e, 0xd509938218066269, 0xd2343389470438bf, 0x3447fb9f941dae35, 0x004de4a9a48ac636,
    0x27ca90f4689c2301, 0x2f3412defbbc0ce5, 0x2ee5bb659869f6c3, 0x15261632db5911f7, 0x4199cac2a1336353, 0xebf5478d0e80e1e5, 0x48e4fa2e689db485, 0x9f8fc1c1df2169c7,
    0x58acc70991dedf76, 0x32bd6dd6df76e594, 0xb1294d9a558addef, 0x939f07081590bd58, 0xe7353289595edd46, 0x6843a58ece448307, 0xa4f54869bbaa00e0, 0x3b74ece02c301fda,
    0xe5c428dbe2f92851, 0xa968e8cd8720a09a, 0x04200b07e3772957, 0xf5ea6a41259fe96b, 0x51ba8890646974d1, 0x23a5b771eb9ef59a, 0x8ce5a677e27e30fa, 0xcd275c9060dad20b,
    0x3db013fabfb3e7f0, 0x05285a98f8dcb9df, 0xfa1f29b103bbb7ef, 0x99b296a1cf43bdea, 0xb4a6f3c0a0b38b3d, 0xaeb12c1aeb5f28d8, 0xae2f1f03eb3e3968, 0x9693b9a888df1b69,
    0xbec2bac7d73e3d13, 0x820cdad7cbb99d6b, 0xfe541ea866e19a24, 0xf8e2001b77881b99, 0x4442c8e030e9d71f, 0x3370b7879f9014e3, 0xb37106c5ed768dff, 0xf5f96b4753b52deb,
    0xeb5b72aa23740779, 0x3c02fd793a6a8c6a, 0xbfb37fd699f63b3d, 0x637caaa95593d047, 0xcc3db0ced7526e79, 0xda0ba925cfaab89c, 0x0a1e599f26764a93, 0x98619f3e4d9ae02b,
    0x9cfce1cf38a28a84, 0x49e24fd3eeb4444f, 0xc55ba9775274a5d1, 0x4039064d18391462, 0x49bad4dba89b74f5, 0x87a4287d22a51523, 0x08007c717cdbd135, 0xfde0ad0c0dc31b17,
    0xfca05d8e9d566c4a, 0xe1c22849a715f865, 0x4f77083d9194bd32, 0x04de5434dc8aa50a, 0x8786c84405db498d, 0x451cf2e8867c0994, 0xf6277144136903e6, 0x3d442f97db571722,
    0x14afeca0645cfaa3, 0x1ca827f4190b6464, 0x9b1a7cb30ee81922, 0xdedbbecf9c1f0335, 0x7f4eb403f969fea2, 0x5ac4f8a651f1348e, 0x003fc5816243b999, 0xe5fe41ff42ee5925,
    0x973631b960509287, 0x06a13b8162813286, 0x9f9f8709acd52ff3, 0x5c11e094abaece8b, 0x354a7913bd03c8a2, 0x2eafde865751f313, 0x0b8712a8ef75ec69, 0xe848590e2df8c405,
    0x60770245efcbc022, 0x218656367a1d7070, 0xf44c069e7f97795e, 0x72b0541de7a5879c, 0x08358548d77ac787, 0x92e2c32dc055d4f8, 0x4cc1abe176a5d932, 0x9ec9aab004d3ff13,
    0x0ee5fd1c3b8aec79, 0x5d8f935675f05c32, 0x68ff2e62e4518e70, 0x501f9f82e0fca152, 0x842603f19c33c874, 0xc735950dc7e2f996, 0x8c1d99be490e3597, 0x8e42d0e66230fe93,
    0xae329aa1564a80e9, 0x5649e17791c1ef21, 0xd02fb4de5056b33c, 0xaf53eb7e9c69160f, 0x526587c48aeb958b, 0xe5bd7f689e8f1d01, 0xfa7c125443e9cf4b, 0xda376c156aa7605a,
    0x7ec566537c0424d6, 0x8c1a06af932c661f, 0xcd9125069014bc3c, 0xee08acb4bbfc0cee, 0xe6501cae883efb79, 0xa6f190b1ce1a8394, 0x2c8f90c4a264b718, 0x34a813d4c676a289,
    0xd9ac28124c66cdb9, 0xa84842ddf899fee5, 0xd6f4dfb2165b1a4a, 0xdd9d2eb71a17b11b, 0xcd78677ebb392b2d, 0xec292883c27357c7, 0xbce91e11f9830d92, 0x7aa8b68435489adb,
    0x54eb584bcdfea954, 0xb8dd62f763e7e58e, 0xa438f6df8db982d8, 0xca9441de3b544abb, 0x1deda190c70f9a4a, 0x445bb6ced6490995, 0x76bf6a3ded7b314d, 0x8a66f016dfdfab07,
    0x64a21901e2bbdbac, 0x191ff6bb807fc7f4, 0x86b368995e99d41e, 0x417e6535be219210, 0x1491867633f53559, 0x0cecb02863af988a, 0x8e4e386e752beffa, 0x4ba58fed077cf4a5,
    0xd777631cb7cc0ef3, 0xe11c0ccd18c90c4f, 0x9343426a5050f38e, 0x55efc291307ee56d, 0x0fbcae5d59aeb627, 0x288b467aa5bdfbca, 0xc0a392953f680019, 0x48916fc91ba84c06,
    0x4a8b4836ba342ed5, 0x03142a9ea4c0e59d, 0xcf342a86d47380b3, 0x3454da8dc9c8791a, 0x0260f14f96803fa0, 0x973bbe79a5f164a8, 0x49edc10d9edee956, 0x0cf5cacd8fccfba6,
    0xdb4f8f51bb534076, 0x470b7f9d70824b90, 0x1a2e4d589fbe3c75, 0xcbc03b148e363146, 0x99ee702383e08652, 0x7d3a7bc2b1d17942, 0xe29dbdde2a789780, 0xd05be133837d8a4a,
    0xf2657c5783404faa, 0xe4c60bef204ebf83, 0x8af681c946077603, 0xa4c30856371c7ea4, 0xfd8491493be53498, 0x65b4bb5c0b432d37, 0xf36cf84d1e69c2fc, 0x72540952b560db4c,
    0x926fe399b48b06bd, 0xbe7bba0600877983, 0x78756a5857287bcf, 0x39344c4f631fab92, 0x8938f0d75f41bb00, 0x62950eb07231d85c, 0x151250c44835e534, 0xeaa6153d366040b6,
    0x0399ff3ab9d2029b, 0x4f9291ac66bea780, 0x5538b8774466b317, 0x104a472bddd01ce6, 0xbb530a2727a7c317, 0x12a408915c974a92, 0x02d8e5447e228765, 0xbb6c944b06c2be01,
    0x860518c2841ca8a0, 0x68edab4683438cfd, 0xd5764f712a25913f, 0x14a6ec6cfa7c3115, 0x6f0cc123ec798547, 0x19ae22cc367c885f, 0xd7be6d5f449e5951, 0x8555f4f8fd21152f,
    0xf3335605e1495f41, 0xb2ea3183d8e360a9, 0xb6221434c5c90c63, 0xdf215d9c2e93390e, 0x98519ef2b0af8143, 0x06044c2d81e1edf6, 0x645f2661d1fc17e2, 0x469a5d2269c3b05f,
    0xca70212744447558, 0x07a4eb3b4b8e8cfd, 0xef200622675d49f9, 0xd7024c3ac1a6d90c, 0x5c54fcec35596bf2, 0x030e135fcb8673a0, 0x9f1cc6537857af20, 0xbf75a9960af6a424,
    0xa1ce52907049fd5f, 0xb85d9f1d69b9e757, 0x85beffbfcc396269, 0x0bdf4af30f73131a, 0x74e5c58ffc16a8fe, 0xc3cc87ed72fe0e64, 0x604c1bc18d443cba, 0x9a1b8fd3634f1d41,
    0xa33795d2516fad6e, 0x99ac9eb1c2ada062, 0xa2713d9be0bcb94d, 0xfd2f6b2989fdf4ea, 0x55e33b2805a13f58, 0x2c7bd9290ee9b966, 0x81fd6f83134014ff, 0x179f8894deefcc6f,
    0xc61c8e56d5fdb3c0, 0xa4e5343bc6afdde1, 0x36ad5e9310f6d4eb, 0xd5fd90a79e27cc78, 0xd8ccd606e4d48e8d, 0x25f66a9cc989fed6, 0x3d0402457fc4bae1, 0x612733dcf3d0d07b,
    0xe38fd4832db05d6c, 0x8e2809b7ea934954, 0x52004f18865f4734, 0xbb8ee10a8dd754c1, 0x0fd0437b265a01b3, 0xad6498e5df9586e8, 0x8e143ecbe7db3bba, 0x17331ca3a86566a0,
    0x50cf16807d23b56d, 0x7c52f40e61c17c15, 0x70aff594054aca7d, 0xa9005fada5801d62, 0xc2c62f1740a8a26d, 0xccccb11f991fb387, 0x2f38ade83ab14eac, 0x33a947c235f4d753,
    0xa5625e617031d563, 0x4f964fabfa8b3b58, 0x84b4e9eaead9b63c, 0x6df29966734e4146, 0x11dd7ce026d0c29a, 0x9963e5fa15f8d521, 0x1e20c4ade063847d, 0xaed43f08f72a9080,
    0x3dd7ce36cef85b37, 0x78e5e46f7874aed5, 0x5ded630f68dab2fa, 0x9e41471fb56fd63b, 0xda4d8c5b0c650d1c, 0x9939dd39cf15b48c, 0xc4caf8da2e6475b3, 0x783e1a913f0b79cb,
    0xd6131558db68427a, 0x544774b505054d4c, 0xa30cadbbabc33d9d, 0xa8d250afca0b7a81, 0x36f07dfcde5fd8d0, 0xd25bb4feb8a0b5d6, 0x52cfde1125affcca, 0x95876763d947df39,
    0x916a38f31aa8c326, 0x7fbdbbe0054a44be, 0xf26e36f7c5eb7a26, 0xdb7ba35f9caacbbd, 0x8de921ce9854cb9c, 0x83c48c8ba5f3ac18, 0xea86332217508916, 0x89d816e3efccd171,
    0xea8314449612a664, 0xf3afd7b04e3e9dcd, 0x0265cf8252d368bc, 0xd9b9f2c5b09ab82e, 0x1be9d93315e7e8e8, 0x4e263044ea592f12, 0x4390a239830f4ecf, 0x55c249d481ef6a4c,
    0xb263e1e7553222ef, 0x11ea971a5642c42c, 0x7894d600bebd1abb, 0xdd6fb6941031338f, 0x29568a2c0c94d52d, 0x01315555449edeb9, 0xb8a03366e13184df, 0xaafa5d4593a6277d,
    0x066b638835960be2, 0xf5215adaeb2e42da, 0x020ebe86ab18e836, 0x1999e5c85d17cc7c, 0xf2d3af28af6c1437, 0x168c7ecd2b437f59, 0xeb96f37a2f474f63, 0x9de6b71e12e31189
};
#if defined(HITLS_SIXTY_FOUR_BITS)
static const BN_UINT g_one[P256_SIZE] = {1, 0, 0, 0};
static const BN_UINT g_sm2Poly[P256_SIZE] = {
    0xffffffffffffffff, 0xffffffff00000000,
    0xffffffffffffffff, 0xfffffffeffffffff
};
static const BN_UINT g_poly2[P256_SIZE] __attribute__((aligned(32))) = {
    0x8000000000000000, 0xffffffff80000000,
    0xffffffffffffffff, 0x7fffffff7fffffff
};
#elif defined(HITLS_THIRTY_TWO_BITS)
static const BN_UINT g_one[P256_SIZE] = {1, 0, 0, 0, 0, 0, 0, 0};
static const BN_UINT g_sm2Poly[P256_SIZE] = {
    0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
    0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe
};
static const BN_UINT g_poly2[P256_SIZE] __attribute__((aligned(16))) = {
    0x00000000, 0x80000000, 0x80000000, 0xffffffff,
    0xffffffff, 0xffffffff, 0x7fffffff, 0x7fffffff
};
#else
#error BN_UINT MUST be 4 or 8
#endif

static uint32_t IsZero(BN_UINT a)
{
    a |= (0 - a);
    a = ~a;
    a >>= (sizeof(BN_UINT) * 8 - 1);
    return a;
}

static uint32_t IsZeros(const BN_UINT *a)
{
    BN_UINT res;
    res = a[0] ^ 0;
    for (uint32_t i = 1; i < P256_SIZE; i++) {
        res |= a[i] ^ 0;
    }
    return IsZero(res);
}

static int IsEqual(const BN_UINT *a, const BN_UINT *b)
{
    BN_UINT res;

    res = a[0] ^ b[0];
    for (uint32_t i = 1; i < P256_SIZE; i++) {
        res |= a[i] ^ b[i];
    }
    return IsZero(res);
}

static int IsGreater(const BN_UINT *a, const BN_UINT *b)
{
    int i;

    for (i = P256_SIZE - 1; i >= 0; --i) {
        if (a[i] > b[i])
            return 1;
        if (a[i] < b[i])
            return -1;
    }

    return 0;
}

static int ECP_Sm2PointEqual(const P256_Point *a, const P256_Point *b)
{
    return IsEqual(a->x.value, b->x.value) && IsEqual(a->y.value, b->y.value) && IsEqual(a->z.value, b->z.value);
}

 /* Montgomery modular inverse: r = a^-1 mod p/n, where n = ord(p) */
static void ECP_Sm2ModInv(BN_UINT *r, const BN_UINT *a)
{
    BN_UINT u[P256_SIZE] __attribute__((aligned(32)));
    BN_UINT v[P256_SIZE] __attribute__((aligned(32)));
    BN_UINT x1[P256_SIZE] __attribute__((aligned(32))) = {1, 0, 0, 0};
    BN_UINT x2[P256_SIZE] __attribute__((aligned(32))) = {0};
    if (IsZeros(a)) {
        return;
    }
    (void)memcpy_s(u, sizeof(u), a, sizeof(u));
    (void)memcpy_s(v, sizeof(v), g_sm2Poly, sizeof(v));
    while (!IsEqual(u, g_one) && !IsEqual(v, g_one)) {
        while (!(u[0] & 1)) {
            ECP_Sm2BnRshift1(u);
            if (!(x1[0] & 1)) {
                ECP_Sm2BnRshift1(x1);
            } else {
                ECP_Sm2BnRshift1(x1);
                ECP_Sm2Add(x1, x1, g_poly2);
            }
        }
        while (!(v[0] & 1)) {
            ECP_Sm2BnRshift1(v);
            if (!(x2[0] & 1)) {
                ECP_Sm2BnRshift1(x2);
            } else {
                ECP_Sm2BnRshift1(x2);
                ECP_Sm2Add(x2, x2, g_poly2);
            }
        }
        if (IsGreater(u, v) == 1) {
            ECP_Sm2Sub(u, u, v);
            ECP_Sm2Sub(x1, x1, x2);
        } else {
            ECP_Sm2Sub(v, v, u);
            ECP_Sm2Sub(x2, x2, x1);
        }
    }
    if (IsEqual(u, g_one)) {
        (void)memcpy_s(r, sizeof(x1), x1, sizeof(x1));
    } else {
        (void)memcpy_s(r, sizeof(x2), x2, sizeof(x2));
    }
}

static int32_t ECP_Sm2Point2Array(P256_Point *r, const ECC_Point *p)
{
    uint32_t len = P256_SIZE;
    int ret = CRYPT_SUCCESS;
#if defined(HITLS_SIXTY_FOUR_BITS)
    GOTO_ERR_IF_EX(BN_Bn2U64Array(p->x, (BN_UINT *)&r->x.value, &len), ret);
    GOTO_ERR_IF_EX(BN_Bn2U64Array(p->y, (BN_UINT *)&r->y.value, &len), ret);
    GOTO_ERR_IF_EX(BN_Bn2U64Array(p->z, (BN_UINT *)&r->z.value, &len), ret);
#else
    GOTO_ERR_IF_EX(BN_BN2Array(p->x, (BN_UINT *)&r->x.value, len), ret);
    GOTO_ERR_IF_EX(BN_BN2Array(p->y, (BN_UINT *)&r->y.value, len), ret);
    GOTO_ERR_IF_EX(BN_BN2Array(p->z, (BN_UINT *)&r->z.value, len), ret);
#endif
ERR:
    return ret;
}

static int32_t ECP_Sm2Array2Point(ECC_Point *r, const P256_Point *a)
{
    uint32_t len = P256_SIZE;
    int ret = CRYPT_SUCCESS;
#if defined(HITLS_SIXTY_FOUR_BITS)
    GOTO_ERR_IF_EX(BN_U64Array2Bn(r->x, (const BN_UINT *)a->x.value, len), ret);
    GOTO_ERR_IF_EX(BN_U64Array2Bn(r->y, (const BN_UINT *)a->y.value, len), ret);
    GOTO_ERR_IF_EX(BN_U64Array2Bn(r->z, (const BN_UINT *)a->z.value, len), ret);
#else
    GOTO_ERR_IF_EX(BN_Array2BN(r->x, (const BN_UINT *)a->x.value, len), ret);
    GOTO_ERR_IF_EX(BN_Array2BN(r->y, (const BN_UINT *)a->y.value, len), ret);
    GOTO_ERR_IF_EX(BN_Array2BN(r->z, (const BN_UINT *)a->z.value, len), ret);
#endif
ERR:
    return ret;
}

int32_t ECP_Sm2GetAffine(P256_AffinePoint *r, const P256_Point *a)
{
    BN_UINT zInv3[P256_SIZE] __attribute__((aligned(32))) = {0};
    BN_UINT zInv2[P256_SIZE] __attribute__((aligned(32))) = {0};
    if (IsZeros(a->z.value)) {
        BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_AT_INFINITY);
        return CRYPT_ECC_POINT_AT_INFINITY;
    }
    if (IsEqual(a->z.value, g_one)) {
        (void)memcpy_s(r->x.value, sizeof(r->x.value), a->x.value, sizeof(r->x.value));
        (void)memcpy_s(r->y.value, sizeof(r->y.value), a->y.value, sizeof(r->x.value));
        return CRYPT_SUCCESS;
    }

    ECP_Sm2ModInv(zInv3, a->z.value);
    ECP_Sm2Sqr(zInv2, zInv3);
    ECP_Sm2Mul(r->x.value, a->x.value, zInv2);
    ECP_Sm2Mul(zInv3, zInv3, zInv2);
    ECP_Sm2Mul(r->y.value, a->y.value, zInv3);

    return CRYPT_SUCCESS;
}

int32_t ECP_Sm2Point2Affine(const ECC_Para *para, ECC_Point *r, const ECC_Point *a)
{
    if (r == NULL || a == NULL || para == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
        return CRYPT_NULL_INPUT;
    }
    if (para->id != CRYPT_ECC_SM2 || r->id != CRYPT_ECC_SM2 || a->id != CRYPT_ECC_SM2) {
        BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_ERR_CURVE_ID);
        return CRYPT_ECC_POINT_ERR_CURVE_ID;
    }

    P256_Point temp = {0};
    P256_AffinePoint rTemp = {0};
    int32_t ret = CRYPT_SUCCESS;

    GOTO_ERR_IF_EX(ECP_Sm2Point2Array(&temp, a), ret);
    GOTO_ERR_IF_EX(ECP_Sm2GetAffine(&rTemp, &temp), ret);
    GOTO_ERR_IF_EX(BN_Array2BN(r->x, rTemp.x.value, P256_SIZE), ret);
    GOTO_ERR_IF_EX(BN_Array2BN(r->y, rTemp.y.value, P256_SIZE), ret);
    GOTO_ERR_IF_EX(BN_SetLimb(r->z, 1), ret);

ERR:
    return ret;
}

void ECP_Sm2PointDbl(P256_Point *r, const P256_Point *a)
{
    unsigned int i;
    BN_UINT T1[P256_SIZE] __attribute__((aligned(32)));
    BN_UINT T2[P256_SIZE] __attribute__((aligned(32)));
    BN_UINT T3[P256_SIZE] __attribute__((aligned(32)));

    /* zero-check a->z.value */
    if (IsZeros(a->z.value)) {
        for (i = 0; i < P256_SIZE; ++i)
            r->z.value[i] = 0;

        return;
    }

    /* 4Mul + 4Sqr */
    ECP_Sm2Sqr(T1, a->z.value);                      /* Z1^2 */
    ECP_Sm2Sub(T2, a->x.value, T1);                  /* X1 - Z1^2 */
    ECP_Sm2Add(T1, a->x.value, T1);                  /* X1 + Z1^2 */
    ECP_Sm2Mul(T2, T2, T1);                          /* X1^2 - Z1^4 */
    ECP_Sm2MulBy3(T2, T2);                           /* T2 = 3*X1^2 - 3*Z1^4 -> lambda_1 */
    ECP_Sm2Add(r->y.value, a->y.value, a->y.value);  /* 2*Y1 */
    ECP_Sm2Mul(r->z.value, r->y.value, a->z.value);  /* Z3 = 2*Y1*Z1 */
    ECP_Sm2Sqr(r->y.value, r->y.value);              /* 4*Y1^2 */
    ECP_Sm2Mul(T3, r->y.value, a->x.value);          /* T3 = 4*X1*Y1^2 -> lambda_2 */
    ECP_Sm2Sqr(r->y.value, r->y.value);
    ECP_Sm2DivBy2(r->y.value, r->y.value);           /* Y3 = 8*Y1^4 -> lambda_3 */
    ECP_Sm2Sqr(r->x.value, T2);
    ECP_Sm2Add(T1, T3, T3);
    ECP_Sm2Sub(r->x.value, r->x.value, T1);          /* X3 = lambda_1^2 - 2*lambda_2 */
    ECP_Sm2Sub(T1, T3, r->x.value);                  /* T1 = lambda_2 - X3 */
    ECP_Sm2Mul(T1, T1, T2);
    ECP_Sm2Sub(r->y.value, T1, r->y.value);          /* Y3 = lambda_1*T1 - lambda_3 */
}

int32_t ECP_Sm2PointDouble(const ECC_Para *para, ECC_Point *r, const ECC_Point *a)
{
    (void)para;
    P256_Point re = {0};
    P256_Point ina = {0};
    int32_t ret = CRYPT_SUCCESS;
    GOTO_ERR_IF_EX(ECP_Sm2Point2Array(&ina, a), ret);
    ECP_Sm2PointDbl(&re, &ina);
    GOTO_ERR_IF_EX(ECP_Sm2Array2Point(r, &re), ret);
ERR:
    return ret;
}

static void ECP_Sm2PointAddJacob(P256_Point *r, const P256_Point *a, const P256_Point *b)
{
    unsigned int i;
    BN_UINT T1[P256_SIZE] __attribute__((aligned(32))) = {0};
    BN_UINT T2[P256_SIZE] __attribute__((aligned(32))) = {0};
    BN_UINT T3[P256_SIZE] __attribute__((aligned(32))) = {0};

    /* zero-check a | b ->z.value */
    if (IsZeros(a->z.value)) {
        for (i = 0; i < P256_SIZE; ++i) {
            r->x.value[i] = b->x.value[i];
            r->y.value[i] = b->y.value[i];
            r->z.value[i] = b->z.value[i];
        }
        return;
    } else if (IsZeros(b->z.value)) {
        for (i = 0; i < P256_SIZE; ++i) {
            r->x.value[i] = a->x.value[i];
            r->y.value[i] = a->y.value[i];
            r->z.value[i] = a->z.value[i];
        }
        return;
    } else if (ECP_Sm2PointEqual(a, b)) {
        ECP_Sm2PointDbl(r, a);
        return;
    }

    /* 12Mul + 4Sqr */
    ECP_Sm2Sqr(T1, b->z.value);                      /* Z2^2 */
    ECP_Sm2Mul(T2, T1, b->z.value);                  /* Z2^3 */
    ECP_Sm2Mul(T1, T1, a->x.value);                  /* T1 = X1*Z2^2             -> lambda_1 */
    ECP_Sm2Mul(T2, T2, a->y.value);                  /* T2 = Y1*Z2^3             -> lambda_4 */
    ECP_Sm2Sqr(T3, a->z.value);                      /* T3 = Z1^2 */
    ECP_Sm2Mul(r->y.value, a->z.value, b->y.value);  /* Y2*Z1 */
    ECP_Sm2Mul(r->z.value, a->z.value, b->z.value);  /* Z1*Z2 */
    ECP_Sm2Mul(r->y.value, T3, r->y.value);          /* Y2*Z1^3                  -> lambda_5 */
    ECP_Sm2Mul(r->x.value, T3, b->x.value);          /* X2*Z1^2                  -> lambda_2 */
    ECP_Sm2Sub(T1, T1, r->x.value);                  /* T1 = X1*Z2^2 - X2*Z1^2   -> lambda_3 */
    ECP_Sm2Mul(r->z.value, T1, r->z.value);          /* Z3 = Z1*Z2*lambda_3 */
    ECP_Sm2Sub(T2, T2, r->y.value);                  /* T2 = Y1*Z2^3 - Y2*Z1^3   -> lambda_6 */
    ECP_Sm2Sqr(T3, T1);                              /* T3 = lambda_3^2 */
    ECP_Sm2Mul(T1, T1, T3);                          /* T1 = lambda_3^3 */
    ECP_Sm2Mul(T3, T3, r->x.value);                  /* T3 = lambda_2*lambda_3^2 */
    ECP_Sm2Sqr(r->x.value, T2);                      /* lambda_6^2 */
    ECP_Sm2Sub(r->x.value, r->x.value, T3);
    ECP_Sm2Sub(r->x.value, r->x.value, T3);
    ECP_Sm2Sub(r->x.value, r->x.value, T1);          /* X3 = lambda_6^2 - 2*lambda_2*lambda_3^2 - lambda_3^3 */
    ECP_Sm2Sub(T3, T3, r->x.value);
    ECP_Sm2Mul(T3, T2, T3);                          /* T3 = lambda_6 * (lambda_2*lambda_3^2 - X3) */
    ECP_Sm2Mul(T1, T1, r->y.value);                  /* T1 = lambda_3^3*lambda_5 */
    ECP_Sm2Sub(r->y.value, T3, T1);                  /* Y3 = T3 - T1 */
}

void ECP_Sm2PointAddAffine(P256_Point *r, const P256_Point *a, const P256_AffinePoint *b)
{
    unsigned int i;
    BN_UINT T1[P256_SIZE] __attribute__((aligned(32))) = {0};
    BN_UINT T2[P256_SIZE] __attribute__((aligned(32))) = {0};
    BN_UINT T3[P256_SIZE] __attribute__((aligned(32))) = {0};
    BN_UINT T4[P256_SIZE] __attribute__((aligned(32))) = {0};

    /* zero-check a->z.value */
    if (IsZeros(a->z.value)) {
        for (i = 0; i < P256_SIZE; ++i) {
            r->x.value[i] = b->x.value[i];
            r->y.value[i] = b->y.value[i];
            r->z.value[i] = 0;
        }
        r->z.value[0] = 1;

        return;
    }

    ECP_Sm2Sqr(T1, a->z.value);
    ECP_Sm2Mul(T2, T1, a->z.value);
    ECP_Sm2Mul(T1, T1, b->x.value);
    ECP_Sm2Mul(T2, T2, b->y.value);
    ECP_Sm2Sub(T1, T1, a->x.value);
    ECP_Sm2Sub(T2, T2, a->y.value);

    /* zero-check T1, T2 */
    if (IsZeros(T1)) {
        if (IsZeros(T2)) {
            P256_Point p;
            for (i = 0; i < P256_SIZE; ++i) {
                p.x.value[i] = b->x.value[i];
                p.y.value[i] = b->y.value[i];
                p.z.value[i] = 0;
            }
            p.z.value[0] = 1;
            ECP_Sm2PointDbl(r, &p);
        } else {
            for (i = 0; i < P256_SIZE; ++i)
                r->z.value[i] = 0;
        }

        return;
    }

    ECP_Sm2Mul(r->z.value, a->z.value, T1);
    ECP_Sm2Sqr(T3, T1);
    ECP_Sm2Mul(T4, T3, T1);
    ECP_Sm2Mul(T3, T3, a->x.value);
    ECP_Sm2Add(T1, T3, T3);
    ECP_Sm2Sqr(r->x.value, T2);
    ECP_Sm2Sub(r->x.value, r->x.value, T1);
    ECP_Sm2Sub(r->x.value, r->x.value, T4);
    ECP_Sm2Sub(T3, T3, r->x.value);
    ECP_Sm2Mul(T3, T3, T2);
    ECP_Sm2Mul(T4, T4, a->y.value);
    ECP_Sm2Sub(r->y.value, T3, T4);
}

// Jacobian add affine
int32_t ECP_Sm2PointAdd(const ECC_Para *para, ECC_Point *r, const ECC_Point *a, const ECC_Point *b)
{
    if (para == NULL || r == NULL || a == NULL || b == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
        return CRYPT_NULL_INPUT;
    }

    P256_Point re = {0};
    P256_Point ina = {0};
    P256_Point inb = {0};
    P256_AffinePoint affb = {0};
    int32_t ret = CRYPT_SUCCESS;
    GOTO_ERR_IF_EX(ECP_Sm2Point2Array(&ina, a), ret);
    GOTO_ERR_IF_EX(ECP_Sm2Point2Array(&inb, b), ret);
    GOTO_ERR_IF_EX(ECP_Sm2GetAffine(&affb, &inb), ret);
    ECP_Sm2PointAddAffine(&re, &ina, &affb);
    GOTO_ERR_IF_EX(ECP_Sm2Array2Point(r, &re), ret);
ERR:
    return ret;
}

void ECP_Sm2ScalarMulG(P256_Point *r, const BN_UINT *k)
{
    const BN_UINT *precompute = (const BN_UINT *)g_sm2Precompute;
    uint32_t index, mask = 0xff;
    for (int i = 31; i >= 0; --i) {
        /* 'i / 8' is for split i to 4 parts(k is a 4 elements array)
           '(8 * (i % 8))' is for the size of k's element is 64bits */
#if defined(HITLS_SIXTY_FOUR_BITS)
        index = (k[i / 8] >> (8 * (i % 8))) & mask;
#else
        index = (k[i / 4] >> (8 * (i % 4))) & mask;
#endif
        ECP_Sm2PointDbl(r, r);
        ECP_Sm2PointDbl(r, r);
        ECP_Sm2PointDbl(r, r);
        ECP_Sm2PointDbl(r, r);
        ECP_Sm2PointDbl(r, r);
        ECP_Sm2PointDbl(r, r);
        ECP_Sm2PointDbl(r, r);
        ECP_Sm2PointDbl(r, r);
        if (index) {
#if defined(HITLS_SIXTY_FOUR_BITS)
            index = index * 8; // 1 point has 64 bytes, which is 8*8 bytes
#else
            index = index * 16; // 1 point has 64 bytes, which is 8*8 bytes
#endif
            ECP_Sm2PointAddAffine(r, r, (const P256_AffinePoint *)&precompute[index]);
        }
    }
}

int32_t ECP_Sm2WindowedMul(P256_Point *r, const BN_UINT *k, P256_AffinePoint *a)
{
    int i;
    unsigned int index, mask = 0x0f;
    P256_Point precomputed[16] __attribute__((aligned(64)));

    BSL_SAL_CleanseData(r, sizeof(P256_Point));

    ECP_Sm2PointAddAffine(&precomputed[1], r, a);
    ECP_Sm2PointDbl(&precomputed[2], &precomputed[1]);
    ECP_Sm2PointAddAffine(&precomputed[3], &precomputed[2], a);
    ECP_Sm2PointDbl(&precomputed[4], &precomputed[2]);
    ECP_Sm2PointAddAffine(&precomputed[5], &precomputed[4], a);
    ECP_Sm2PointDbl(&precomputed[6], &precomputed[3]);
    ECP_Sm2PointAddAffine(&precomputed[7], &precomputed[6], a);
    ECP_Sm2PointDbl(&precomputed[8], &precomputed[4]);
    ECP_Sm2PointAddAffine(&precomputed[9], &precomputed[8], a);
    ECP_Sm2PointDbl(&precomputed[10], &precomputed[5]);
    ECP_Sm2PointAddAffine(&precomputed[11], &precomputed[10], a);
    ECP_Sm2PointDbl(&precomputed[12], &precomputed[6]);
    ECP_Sm2PointAddAffine(&precomputed[13], &precomputed[12], a);
    ECP_Sm2PointDbl(&precomputed[14], &precomputed[7]);
    ECP_Sm2PointAddAffine(&precomputed[15], &precomputed[14], a);

    for (i = 63; i >= 0; --i) {
#if defined(HITLS_SIXTY_FOUR_BITS)
        index = (k[i / 16] >> (4 * (i % 16))) & mask;
#else
        index = (k[i / 8] >> (4 * (i % 8))) & mask;
#endif
        ECP_Sm2PointDbl(r, r);
        ECP_Sm2PointDbl(r, r);
        ECP_Sm2PointDbl(r, r);
        ECP_Sm2PointDbl(r, r);
        if (index)
            ECP_Sm2PointAddJacob(r, r, &precomputed[index]);
    }
    return CRYPT_SUCCESS;
}

int32_t ECP_Sm2PointMul(ECC_Para *para, ECC_Point *r, const BN_BigNum *scalar, const ECC_Point *pt)
{
    if (para == NULL || r == NULL || scalar == NULL) {
        BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
        return CRYPT_NULL_INPUT;
    }
    if (para->id != CRYPT_ECC_SM2 || r->id != CRYPT_ECC_SM2 || (pt != NULL && (pt->id != CRYPT_ECC_SM2))) {
        BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_ERR_CURVE_ID);
        return CRYPT_ECC_POINT_ERR_CURVE_ID;
    }
    if (pt != NULL && BN_IsZero(pt->z)) {
        BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_AT_INFINITY);
        return CRYPT_ECC_POINT_AT_INFINITY;
    }
    if (BN_IsZero(scalar)) {
        BN_Zeroize(r->z);
        return CRYPT_SUCCESS;
    }
    int32_t ret = CRYPT_SUCCESS;
    BN_UINT k[P256_SIZE] = {0};
    uint32_t klen = P256_SIZE;
    P256_Point re = {0};
    P256_Point sm2Pt = {0};
    P256_AffinePoint sm2Aff = {0};
#if defined(HITLS_SIXTY_FOUR_BITS)
    GOTO_ERR_IF_EX(BN_Bn2U64Array(scalar, k, &klen), ret);
#else
    GOTO_ERR_IF_EX(BN_BN2Array(scalar, k, klen), ret);
#endif
    if (pt == NULL) {
        // calculate k*G
        ECP_Sm2ScalarMulG(&re, k);
        // P256_Point 2 ECC_Point
        GOTO_ERR_IF_EX(ECP_Sm2Array2Point(r, &re), ret);
    } else {
        // point 2 affine
        GOTO_ERR_IF_EX(ECP_Sm2Point2Array(&sm2Pt, pt), ret);
        GOTO_ERR_IF_EX(ECP_Sm2GetAffine(&sm2Aff, &sm2Pt), ret);
        GOTO_ERR_IF_EX(ECP_Sm2WindowedMul(&re, k, &sm2Aff), ret);
        // P256_Point 2 ECC_Point
        GOTO_ERR_IF_EX(ECP_Sm2Array2Point(r, &re), ret);
    }

ERR:
    return ret;
}

#endif
